package gov.pbc.nn.core.bdf.authoritydelegation.view.select;

import gov.pbc.nn.core.bdf.authoritydelegation.AuthoritydelegationHibernateDao;
import gov.pbc.nn.core.bdf.authoritydelegation.service.IAuthoritydelegationService;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.stereotype.Component;

import com.bstek.bdf2.core.business.IDept;
import com.bstek.bdf2.core.business.IUser;
import com.bstek.bdf2.core.context.ContextHolder;
import com.bstek.bdf2.core.service.IDeptService;
import com.bstek.dorado.annotation.DataProvider;

/**
 * @author lucas.yue@bstek.com
 * 
 *         2013-4-20 下午11:26:24
 */
@Component("bdf2.deptSelectAd")
public class DeptSelect extends AuthoritydelegationHibernateDao {
	private IDeptService deptService;

	@DataProvider
	public Collection<IDept> loadDepts(String parentId) throws Exception {
		IUser user = ContextHolder.getLoginUser();
		if (user == null) {
			throw new RuntimeException("Please login first");
		}
		String companyId = user.getCompanyId();
		if (StringUtils.isNotEmpty(getFixedCompanyId())) {
			companyId = getFixedCompanyId();
		}
		if(StringUtils.isEmpty(parentId)){
			if(user.isAdministrator()){
				parentId = "#########";
			}
		}
		if (user.isAdministrator()) {
			deptService = ContextHolder.getBean(IDeptService.BEAN_ID);
			List<IDept> deptList = deptService.loadDeptsByParentId(parentId, companyId);
			return deptList;
//			List<Map<String, Object>> depts = new ArrayList<Map<String, Object>>();
//			for (IDept dept : topDeptList) {
//				Map<String, Object> deptMap = this.toMap(dept);
//				this.getChildren(deptMap, companyId);
//				depts.add(deptMap);
//			}
//			return depts;
		} else {
			IAuthoritydelegationService ad = ContextHolder.getBean(IAuthoritydelegationService.BEAN_ID_);
			Collection<IDept> deptList = ad.findControllableDepts(user.getUsername(),parentId);
			return deptList;
//			List<Map<String, Object>> depts = new ArrayList<Map<String, Object>>();
//			Map<String, Map<String, Object>> cache = new HashMap<String, Map<String, Object>>();
//			Set<String> set = new HashSet<String>();
//			for (IDept d : deptList) {
//				Map<String, Object> deptMap = this.getTopDept(this.toMap(d), deptList, cache);
//				if (!set.contains(deptMap.get("id"))) {
//					set.add((String) deptMap.get("id"));
//					depts.add(deptMap);
//				}
//			}
//			return depts;
		}
	}

	private Map<String, Object> getTopDept(Map<String, Object> dept, Collection<IDept> depts,
			Map<String, Map<String, Object>> cache) throws Exception {
		if (StringUtils.isEmpty((String) dept.get("parentId"))) {
			return dept;
		} else {
			for (IDept d : depts) {
				if (dept.get("id").equals(d.getId()))
					continue;
				if (dept.get("parentId").equals(d.getId())) {
					Map<String, Object> parent = cache.get(d.getId());
					if (parent == null) {
						parent = this.toMap(d);
						cache.put(d.getId(), parent);
					}
					List<Map<String, Object>> children = new ArrayList<Map<String, Object>>();
					children.add(dept);

					parent.put("children", children);

					return this.getTopDept(parent, depts, cache);
				}
			}
		}
		return dept;
	}

	private void getChildren(Map<String, Object> dept, String companyId) throws Exception {
		List<IDept> depts = deptService.loadDeptsByParentId((String) dept.get("id"), companyId);
		List<Map<String, Object>> children = new ArrayList<Map<String, Object>>();
		for (IDept d : depts) {
			children.add(this.toMap(d));
		}
		dept.put("children", children);

		for (Map<String, Object> d : children) {
			this.getChildren(d, companyId);
		}
	}

	@SuppressWarnings("unchecked")
	private Map<String, Object> toMap(IDept dept) throws Exception {
		ObjectMapper mapper = new ObjectMapper();
		String json = mapper.writeValueAsString(dept);
		return mapper.readValue(json, Map.class);
	}

}
